import Cookies from 'js-cookie'
// cookie保存的天数
import config from '@/config'
import {
  hasOneOf,
  objEqual
} from '@/libs/tools'
const {
  title,
  cookieExpires
} = config

export const TOKEN_KEY = 'token'

export const setToken = (token) => {
  Cookies.set(TOKEN_KEY, token, {
    expires: cookieExpires || 1
  })
}

export const getToken = () => {
  const token = Cookies.get(TOKEN_KEY)
  if (token) return token
  else return false
}

export const hasChild = (item) => {
  return item.children && item.children.length > 0
}

// const showThisMenuEle = (item, access) => {
//   if (item.meta && item.meta.access && item.meta.access.length) {
//     if (hasOneOf(item.meta.access, access)) return true
//     else return false
//   } else return true
// }
/**
 * @param {Array} list 通过路由列表得到菜单列表
 * @returns {Array}
 */
// export const getMenuByRouter = (list, access) => {
//   let res = []
//   forEach(list, item => {
//     if (!item.meta || (item.meta && !item.meta.hideInMenu)) {
//       let obj = {
//         icon: (item.meta && item.meta.icon) || '',
//         name: item.name,
//         meta: item.meta
//       }
//       if ((hasChild(item) || (item.meta && item.meta.showAlways)) && showThisMenuEle(item, access)) {
//         obj.children = getMenuByRouter(item.children, access)
//       }
//       if (item.meta && item.meta.href) obj.href = item.meta.href
//       if (showThisMenuEle(item, access)) res.push(obj)
//     }
//   })
//   return res
// }
export const getMenuByRouter = (list, access) => {
  let res = []
  access.forEach(item => {
    if (item.resChildren && item.resChildren.length > 0) {
      item.meta = item.meta ? item.meta : {}
      // item.id = item.id;
      item.meta.title = item.name
      item.icon = item.resIcon || ''
      item.name = item.resCode
      item.children = getMenuByRouter(list, item.resChildren)
      res.push(item)
    } else {
      // console.log(item.url);
      if (item.url) {
        if (item.url.indexOf('.html') !== '-1') {
          const arr = getParamFormRouter(list, item)
          if (arr.length > 0) {
            let params = arr[0]
            params.icon = item.resIcon || params.icon || ''
            params.meta = params.meta ? params.meta : {}
            params.meta.title = item.name
            params.id = item.id
            res.push(params)
          } else {
            // console.log(1);
            res.push({
              icon: item.resIcon,
              type: 'url',
              id: item.id,
              meta: {
                title: item.name
              },
              name: item.resCode,
              path: item.url
            })
          }
        } else {
          res.push({
            icon: item.resIcon,
            type: 'url',
            id: item.id,
            name: item.resCode,
            meta: {
              title: item.name
            },
            path: item.url
          })
        }
      } else {
        res.push({
          icon: item.resIcon,
          type: 'url',
          id: item.id,
          meta: {
            title: item.name
          },
          name: item.resCode,
          path: item.url
        })
      }
    }
  })
  return res
}

function getParamFormRouter (list, obj) {
  let res = []
  let bool = true
  list.forEach(item => {
    if (bool) {
      if (hasChild(item)) {
        const pp = getParamFormRouter(item.children, obj)
        if (pp.length > 0) {
          bool = false
          res.push(pp[0])
        }
      } else {
        if (item.name === obj.resCode) {
          bool = false
          res.push({
            path: obj.url,
            name: item.name,
            redirect: item.redirect,
            component: item.component,
            meta: item.meta
          })
        }
      }
    }
  })
  return res
}

export const getRouteByName = (route, name) => {
  let res = []
  let bool = true
  route.forEach(item => {
    if (bool) {
      if (hasChild(item)) {
        const pp = getRouteByName(item.children, name)
        if (pp.length > 0) {
          bool = false
          res.push(pp[0])
        }
      } else {
        if (item.name === name) {
          bool = false
          res.push(item)
        }
      }
    }
  })
  return res
}

const getParam = (arr, url) => {
  let params = {}
  let bool = true
  for (let i = 0; i < arr.length; i++) {
    if (bool) {
      const item = arr[i]
      if (item.name === url) {
        bool = false
        params = {
          path: item.path,
          name: item.name,
          redirect: item.redirect,
          component: item.component,
          meta: item.meta
        }
        return
      } else {
        if (hasChild(item)) {
          const pp = getParam(item.children, url)
          if (pp.name) {
            // eslint-disable-next-line no-undef
            param = pp
          }
        }
      }
    }
  }
  return params
}

/**
 * @param {Array} routeMetched 当前路由metched
 * @returns {Array}
 */
export const getBreadCrumbList = (route, homeRoute) => {
  let homeItem = {
    ...homeRoute,
    icon: homeRoute.meta.icon
  }
  let routeMetched = route.matched
  if (routeMetched.some(item => item.name === homeRoute.name)) return [homeItem]
  let res = routeMetched.filter(item => {
    return item.meta === undefined || !item.meta.hideInBread
  }).map(item => {
    let meta = {
      ...item.meta
    }
    if (meta.title && typeof meta.title === 'function') {
      meta.__titleIsFunction__ = true
      meta.title = meta.title(route)
    }
    let obj = {
      icon: (item.meta && item.meta.icon) || '',
      name: item.name,
      meta: meta
    }
    return obj
  })
  res = res.filter(item => {
    return !item.meta.hideInMenu
  })
  return [{
    ...homeItem,
    to: homeRoute.path
  }, ...res]
}

export const getRouteTitleHandled = (route) => {
  let router = {
    ...route
  }
  let meta = {
    ...route.meta
  }
  let title = ''
  if (meta.title) {
    if (typeof meta.title === 'function') {
      meta.__titleIsFunction__ = true
      title = meta.title(router)
    } else title = meta.title
  }
  meta.title = title
  router.meta = meta
  return router
}

export const showTitle = (item, vm) => {
  let {
    title } = item.meta
  if (!title) return
  // if (useI18n) {
  //   if (title.includes('{{') && title.includes('}}') && useI18n) title = title.replace(/({{[\s\S]+?}})/, (m, str) => str.replace(/{{([\s\S]*)}}/, (m, _) => vm.$t(_.trim())))
  //   else if (__titleIsFunction__) title = item.meta.title
  //   else title = vm.$t(item.name)
  // } else
  title = (item.meta && item.meta.title) || item.name
  return title
}

/**
 * @description 本地存储和获取标签导航列表
 */
export const setTagNavListInLocalstorage = list => {
  // localStorage.tagNaveList = JSON.stringify(list);
  sessionStorage.tagNaveList = JSON.stringify(list)
}
/**
 * @returns {Array} 其中的每个元素只包含路由原信息中的name, path, meta三项
 */
export const getTagNavListFromLocalstorage = () => {
  // const list = localStorage.tagNaveList;
  const list = sessionStorage.tagNaveList
  return list ? JSON.parse(list) : []
}

/**
 * @param {Array} routers 路由列表数组
 * @description 用于找到路由列表中name为home的对象
 */
export const getHomeRoute = (routers, homeName = 'home') => {
  let i = -1
  let len = routers.length
  let homeRoute = {}
  while (++i < len) {
    let item = routers[i]
    if (item.children && item.children.length) {
      let res = getHomeRoute(item.children, homeName)
      if (res.name) {
        return res
      }
    } else {
      if (item.name === homeName) {
        homeRoute = item
      }
    }
  }
  return homeRoute
}

/**
 * @param {*} list 现有标签导航列表
 * @param {*} newRoute 新添加的路由原信息对象
 * @description 如果该newRoute已经存在则不再添加
 */
export const getNewTagList = (list, newRoute) => {
  return [newRoute]

  // :TODO 处理面包屑导航处理
  // const {
  //   name,
  //   path,
  //   meta
  // } = newRoute;
  // let newList = [...list];
  // if (newList.findIndex(item => item.name === name) >= 0) return newList;
  // else newList.push({
  //   name,
  //   path,
  //   meta
  // });
  // return newList;
}

/**
 * @param {*} access 用户权限数组，如 ['super_admin', 'admin']
 * @param {*} route 路由列表
 */
const hasAccess = (access, route) => {
  if (route.meta && route.meta.access) {
    return hasOneOf(access, route.meta.access)
  } else {
    return true
  }
}

/**
 * 权鉴
 * @param {*} name 即将跳转的路由name
 * @param {*} access 用户权限数组
 * @param {*} routes 路由列表
 * @description 用户是否可跳转到该页
 */
export const canTurnTo = (name, access, routes) => {
  const routePermissionJudge = (list) => {
    return list.some(item => {
      if (item.children && item.children.length) {
        return routePermissionJudge(item.children)
      } else if (item.name === name) {
        return hasAccess(access, item)
      }
    })
  }

  return routePermissionJudge(routes)
}

/**
 * @param {String} url
 * @description 从URL中解析参数
 */
export const getParams = url => {
  const keyValueArr = url.split('?')[1].split('&')
  let paramObj = {}
  keyValueArr.forEach(item => {
    const keyValue = item.split('=')
    paramObj[keyValue[0]] = keyValue[1]
  })
  return paramObj
}

/**
 * @param {Array} list 标签列表
 * @param {String} name 当前关闭的标签的name
 */
export const getNextRoute = (list, route) => {
  let res = {}
  if (list.length === 2) {
    res = getHomeRoute(list)
  } else {
    const index = list.findIndex(item => routeEqual(item, route))
    if (index === list.length - 1) {
      res = list[list.length - 2]
    } else {
      res = list[index + 1]
    }
  }
  return res
}

/**
 * @param {Number} times 回调函数需要执行的次数
 * @param {Function} callback 回调函数
 */
export const doCustomTimes = (times, callback) => {
  let i = -1
  while (++i < times) {
    callback(i)
  }
}

/**
 * @param {Object} file 从上传组件得到的文件对象
 * @returns {Promise} resolve参数是解析后的二维数组
 * @description 从Csv文件中解析出表格，解析成二维数组
 */
export const getArrayFromFile = (file) => {
  let nameSplit = file.name.split('.')
  let format = nameSplit[nameSplit.length - 1]
  return new Promise((resolve, reject) => {
    let reader = new FileReader()
    reader.readAsText(file) // 以文本格式读取
    let arr = []
    reader.onload = function (evt) {
      let data = evt.target.result // 读到的数据
      let pasteData = data.trim()
      arr = pasteData.split((/[\n\u0085\u2028\u2029]|\r\n?/g)).map(row => {
        return row.split('\t')
      }).map(item => {
        return item[0].split(',')
      })
      if (format === 'csv') {
        resolve(arr)
      } else {
        reject(new Error('[Format Error]:你上传的不是Csv文件'))
      }
    }
  })
}

/**
 * @param {Array} array 表格数据二维数组
 * @returns {Object} { columns, tableData }
 * @description 从二维数组中获取表头和表格数据，将第一行作为表头，用于在iView的表格中展示数据
 */
export const getTableDataFromArray = (array) => {
  let columns = []
  let tableData = []
  if (array.length > 1) {
    let titles = array.shift()
    columns = titles.map(item => {
      return {
        title: item,
        key: item
      }
    })
    tableData = array.map(item => {
      let res = {}
      item.forEach((col, i) => {
        res[titles[i]] = col
      })
      return res
    })
  }
  return {
    columns,
    tableData
  }
}

export const findNodeUpper = (ele, tag) => {
  if (ele.parentNode) {
    if (ele.parentNode.tagName === tag.toUpperCase()) {
      return ele.parentNode
    } else {
      return findNodeUpper(ele.parentNode, tag)
    }
  }
}

export const findNodeUpperByClasses = (ele, classes) => {
  let parentNode = ele.parentNode
  if (parentNode) {
    let classList = parentNode.classList
    if (classList && classes.every(className => classList.contains(className))) {
      return parentNode
    } else {
      return findNodeUpperByClasses(parentNode, classes)
    }
  }
}

export const findNodeDownward = (ele, tag) => {
  const tagName = tag.toUpperCase()
  if (ele.childNodes.length) {
    let i = -1
    let len = ele.childNodes.length
    while (++i < len) {
      let child = ele.childNodes[i]
      if (child.tagName === tagName) return child
      else return findNodeDownward(child, tag)
    }
  }
}

export const showByAccess = (access, canViewAccess) => {
  return hasOneOf(canViewAccess, access)
}

/**
 * @description 根据name/params/query判断两个路由对象是否相等
 * @param {*} route1 路由对象
 * @param {*} route2 路由对象
 */
export const routeEqual = (route1, route2) => {
  const params1 = route1.params || {}
  const params2 = route2.params || {}
  const query1 = route1.query || {}
  const query2 = route2.query || {}
  return (route1.name === route2.name) && objEqual(params1, params2) && objEqual(query1, query2)
}

/**
 * 判断打开的标签列表里是否已存在这个新添加的路由对象
 */
export const routeHasExist = (tagNavList, routeItem) => {
  let len = tagNavList.length
  let res = false
  doCustomTimes(len, (index) => {
    if (routeEqual(tagNavList[index], routeItem)) {
      res = true
    }
  })
  return res
}

export const localSave = (key, value) => {
  // localStorage.setItem(key, value);
  sessionStorage.setItem(key, value)
}

export const localRead = (key) => {
  // return localStorage.getItem(key) || '';
  return sessionStorage.getItem(key) || ''
}

// scrollTop animation
export const scrollTop = (el, from = 0, to, duration = 500, endCallback) => {
  if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = (
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.msRequestAnimationFrame ||
      function (callback) {
        return window.setTimeout(callback, 1000 / 60)
      }
    )
  }
  const difference = Math.abs(from - to)
  const step = Math.ceil(difference / duration * 50)

  const scroll = (start, end, step) => {
    if (start === end) {
      endCallback && endCallback()
      return
    }

    let d = (start + step > end) ? end : start + step
    if (start > end) {
      d = (start - step < end) ? end : start - step
    }

    if (el === window) {
      window.scrollTo(d, d)
    } else {
      el.scrollTop = d
    }
    window.requestAnimationFrame(() => scroll(d, end, step))
  }
  scroll(from, to, step)
}

/**
 * @description 根据当前跳转的路由设置显示在浏览器标签的title
 * @param {Object} routeItem 路由对象
 * @param {Object} vm Vue实例
 */
export const setTitle = (routeItem, vm) => {
  const handledRoute = getRouteTitleHandled(routeItem)
  const pageTitle = showTitle(handledRoute, vm)
  const resTitle = pageTitle ? `${title} - ${pageTitle}` : title
  window.document.title = resTitle
}

// 格式化资源树
export const formatResourceTree = (data) => {
  const datas = data.map(item => {
    if (item.resChildren) {
      item.children = formatResourceTree(item.resChildren)
    }
    return item
  })
  return datas
}
/**
 * 添加本地树
 * @param {array} data 树data
 * @param {object} param1 父节点
 * @param {object} param2 新节点
 */
export const addTreeLocal = (data, pNode, newNode) => {
  const {
    name,
    id
  } = newNode
  const {
    pid
  } = pNode
  let arr = data.map(item => {
    if (item.id === pid) {
      if (item.children) {
        item.children.push({
          name,
          id,
          children: []
        })
      } else {
        item.children = [{
          name,
          id,
          children: []
        }]
      }
    } else {
      if (item.children && item.children.length > 0) {
        addTreeLocal(item.children, pNode, newNode)
      }
    }
    return item
  })
  return arr
}
/**
 * 修改本地树
 * @param {array} data 树data
 * @param {object} param1 新节点
 */
export const editTreeLocal = (data, editNode) => {
  const {
    name,
    id
  } = editNode
  let arr = data.map(item => {
    if (item.id === id) {
      item.name = name
    } else {
      if (item.children && item.children.length > 0) {
        editTreeLocal(item.children, editNode)
      }
    }
    return item
  })
  return arr
}
/**
 * 删除本地树
 * @param {array} data 树data
 * @param {object} param1 删除的节点
 */
export const deleteTreeLocal = (data, node) => {
  const {
    id
  } = node
  const arr = data.filter(item => {
    if (item.id === id) {
      return false
    } else {
      if (item.children && item.children.length > 0) {
        item.children = deleteTreeLocal(item.children, node)
      }
      return true
    }
  })
  return arr
}

export const getUrlKey = (name) => {
  let reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
  let r = window.location.search.substr(1).match(reg)
  if (r != null) return unescape(r[2])
  return null
}

/**
 * 重新 格式化 后台返回的树数据
 * @param {array} treeDatas 树data
 * @param {string} childrensName children的key值，可能是resChildren
 */
export const transferTree = (treeDatas, childrensName = 'children') => {
  const realtree = treeDatas.map(item => {
    if (item[childrensName] && item[childrensName].length > 0) {
      const arr = item.checked
        ? getParentCheck(item[childrensName], childrensName)
        : getChilrenCheck(item[childrensName], childrensName)
      item.checked = arr[0]
      item.halfcheck = arr[1]
      item.children = transferTree(item[childrensName], childrensName)
    }
    return item
  })
  return realtree
}

const getParentCheck = (childrens, childrensName) => {
  let bool = true
  let childrenCheckLen = 0
  let halfcheck = false
  childrens.forEach(item => {
    if (item[childrensName] && item[childrensName].length > 0) {
      const boolArr = getParentCheck(item[childrensName], childrensName)
      if (boolArr[1]) {
        bool = false
        halfcheck = true
      } else {
        if (boolArr[0]) {
          childrenCheckLen++
        } else {
          bool = false
        }
      }
    } else {
      if (item.checked) {
        childrenCheckLen++
      } else {
        bool = false
      }
    }
  })
  if (childrenCheckLen > 0 && childrenCheckLen < childrens.length) {
    halfcheck = true
  }
  return [bool, halfcheck]
}
const getChilrenCheck = (childrens, childrensName) => {
  let childrenCheckLen = 0
  const length = childrens.length
  childrens.forEach(item => {
    if (item.checked) {
      childrenCheckLen++
    } else {
      if (item[childrensName] && item[childrensName].length > 0) {
        const boolArr = getChilrenCheck(item[childrensName], childrensName)
        if (boolArr[0] || boolArr[1]) {
          childrenCheckLen++
        }
      }
    }
  })
  return [
    childrenCheckLen === length, childrenCheckLen > 0 && childrenCheckLen < length
  ]
}
